package vip.ifmm.lehouse.user.service.api.impl;

import com.alibaba.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import vip.ifmm.lehouse.common.dto.ServerResponse;
import vip.ifmm.lehouse.common.enums.CommonStatus;
import vip.ifmm.lehouse.common.enums.status.UserRegisterStatus;
import vip.ifmm.lehouse.common.model.User;
import vip.ifmm.lehouse.common.model.empty.EmptyUser;
import vip.ifmm.lehouse.common.util.CodeUtil;
import vip.ifmm.lehouse.common.util.Md5Util;
import vip.ifmm.lehouse.user.service.api.UserRegisterService;
import vip.ifmm.lehouse.user.service.dao.UserRegisterDao;
import vip.ifmm.lehouse.user.service.event.SendRegisterCodeEvent;
import vip.ifmm.lehouse.user.service.utils.RedisUtil;

import javax.annotation.Resource;

/**
 * 用户注册服务实现类
 *
 * @author Fish
 * <p>Email: fishinlove@163.com</p>
 * <p>created by 2019/06/16 16:55:34</p>
 */
@Service(owner = "fish", mock = "vip.ifmm.lehouse.user.service.api.mock.UserRegisterServiceMock", timeout = 5000)
public class UserRegisterServiceImpl implements UserRegisterService {

    @Value("${default-head-image}")
    private String defaultHeadImage = "";

    @Value("${register-code-expire}")
    private int registerCodeExpire = 90;

    // 注册验证码的 key 的前缀
    private static final String REGISTER_CODE_KEY_PREFIX = "register-code-of:";

    // 用户注册的持久层
    @Resource
    private UserRegisterDao registerDao = null;

    // Spring 上下文
    @Resource
    private ApplicationContext context = null;

    @Override
    public ServerResponse<Object> register(String code, String email, String password) {

        // 先执行注册前操作
        ServerResponse<Object> beforeRegister = beforeRegister(code, email, password);
        if (!beforeRegister.isSuccess()) {
            return beforeRegister;
        }

        // 可以进行注册
        User user = EmptyUser.me();
        user.setUserNickname(email);
        user.setUserEmail(email);
        user.setUserHeadImage(defaultHeadImage);
        user.setUserPassword(Md5Util.DoubleMD5(password));

        // 保存用户对象
        int count = registerDao.saveUser(user);
        if (count <= 0) {
            return ServerResponse.response(UserRegisterStatus.FAILED);
        }
        return ServerResponse.response(UserRegisterStatus.SUCCESS);
    }

    @Override
    public ServerResponse<Boolean> isEmailUsed(String email) {

        // 检查邮箱是否为空
        if (CodeUtil.isBlank(email)) {
            return ServerResponse.response(UserRegisterStatus.EMAIL_IS_EMPTY, false);
        }

        // 邮箱已经被使用
        if (existed(email)) {
            return ServerResponse.response(UserRegisterStatus.EMAIL_IS_USED, false);
        }

        // 邮箱可以使用
        return ServerResponse.response(UserRegisterStatus.EMAIL_IS_OK, true);
    }

    @Override
    public ServerResponse<Object> sendRegisterCode(String toWho) {

        // 将验证码保存在一个地方，用于验证
        final String registerCode = registerCode();
        putRegisterCode(toWho, registerCode);

        // 发布一个事件，这个事件会通知监听器进行发送注册验证码
        context.publishEvent(new SendRegisterCodeEvent(toWho, registerCode));
        return ServerResponse.response(UserRegisterStatus.REGISTER_CODE_SENT);
    }

    // 将邮箱验证码存进 Redis
    private void putRegisterCode(String toWho, String registerCode) {
        RedisUtil.set(registerCodeKey(toWho), registerCode, registerCodeExpire);
    }

    // 在注册之前执行一些操作
    // 如果返回的状态码不是成功码将不会执行注册操作
    @SuppressWarnings("unchecked")
    private ServerResponse<Object> beforeRegister(String code, String email, String password) {
        // 验证邮箱是否为空
        if (CodeUtil.isBlank(email)) {
            return ServerResponse.response(UserRegisterStatus.EMAIL_IS_EMPTY);
        }

        // 验证密码是否为空
        if (CodeUtil.isBlank(password)) {
            return ServerResponse.response(UserRegisterStatus.PASSWORD_IS_EMPTY);
        }

        // 判断邮箱是否已经被使用
        ServerResponse emailUsed = isEmailUsed(email);
        if (!emailUsed.isSuccess() || !((Boolean) emailUsed.getData())) {
            return emailUsed;
        }

        // 验证邮箱验证码
        String realCode = RedisUtil.get(registerCodeKey(email), String.class);
        if (CodeUtil.isBlank(realCode) || !realCode.equals(code)) {
            return ServerResponse.response(UserRegisterStatus.REGISTER_CODE_IS_INCORRECT);
        }

        // 通过验证
        return ServerResponse.response(CommonStatus.SUCCESS);
    }

    // 检查邮箱是否已经被使用
    private boolean existed(String email) {
        return registerDao.countUserByEmail(email) > 0;
    }

    // 获得注册验证码
    private String registerCode() {
        return CodeUtil.randomString(6);
    }

    // 得到邮箱验证码
    private String registerCodeKey(String toWho) {
        return REGISTER_CODE_KEY_PREFIX + toWho;
    }
}
